import {parse, EvalAstFactory} from "jexpr";


// An EvalAstFactory produces an AST that can be evaluated
const astFactory = new EvalAstFactory();

export function getAll(ast, stype = "ID") {
    let ids = [];
    function  travel(v, {parent, type} = {}) {
        if (v.type === type) {
            if (type === "Getter") {
                console.log(v, parent)
                let s = []
                v.getIds(s)
                let str = '';
                s.forEach(item => {
                    str = str + item + '.'
                })
                ids.push( str + v.name);
            }
            else if (type === "Invoke") {
                v.arguments.forEach(item => {
                    if (item.type === 'ID') {
                        ids.push(item.value)
                    }
                    travel(item, {parent: v, type: 'Getter'});
                })
            }
            else {
                if (parent && parent.type === "Getter") {

                }
                else {
                    ids.push(v.value);
                }
            }
        }
        else {
            if (v.left) {
                travel(v.left, {
                    parent: v,
                    type
                });
            }
            if (v.right) {
                travel(v.right, {
                    parent: v,
                    type
                });
            }

        }
    }
    travel(ast, {
        parent: null,
        type: stype,
    });
    // console.log(ids);
    return ids;
}

export function getExprAst(code) {
    return  parse(code, astFactory);
}
globalThis._getExprAst = getExprAst

export let COMMON_FUN = {
    len: function (v) {
        if (typeof v === 'undefined') {
            return 0
        }
        return v?.length;
    }
}

export function runExpr(code = '', data = {}, ext = {}) {
    // parse() returns the AST
    let expr = parse(code, astFactory);
    // console.log(expr)
    let result = expr.evaluate({
        ...data,
        ...ext
    });
    expr = null
    return result
}
globalThis._runExpr = runExpr

export let _getZCondVars = function (cond = '', conds = new Set()) {
    let obj = getExprAst(cond);
    console.log('_getZCondVars', obj);
    let ids = getAll(obj, "ID");
    ids.forEach(getter => {
        conds.add(getter);
    })
    let getters = getAll(obj, "Getter")
    getters.forEach(getter => {
        conds.add(getter);
    });
    let invokes = getAll(obj, "Invoke");
    invokes.forEach(getter => {
        conds.add(getter);
    });
    console.log('conds', [...conds]);
}
globalThis._getZCondVars = _getZCondVars
globalThis._testZConds = function (cond) {
    let set  = new Set()
    _getZCondVars(cond, set);
    return [...set]
}